#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
AIOT智能学习桌项目 - 语音识别模块 (离线版)
使用本地语音识别，不依赖网络连接
支持Windows系统语音识别和简单的语音转文字功能
"""

import speech_recognition as sr
import threading
import queue
import time
import sys
from datetime import datetime
import json
import os

class OfflineVoiceRecognizer:
    """离线语音识别器类"""
    
    def __init__(self, language='zh-CN', timeout=2, phrase_time_limit=5):
        """
        初始化离线语音识别器
        
        Args:
            language: 识别语言，默认中文
            timeout: 监听超时时间
            phrase_time_limit: 单次识别时间限制
        """
        self.language = language
        self.timeout = timeout
        self.phrase_time_limit = phrase_time_limit
        
        # 初始化识别器和麦克风
        self.recognizer = sr.Recognizer()
        self.microphone = sr.Microphone()
        
        # 语音识别结果队列
        self.result_queue = queue.Queue()
        
        # 控制标志
        self.is_listening = False
        self.is_running = False
        
        # 识别统计
        self.recognition_count = 0
        self.success_count = 0
        self.error_count = 0
        
        # 调整麦克风
        self._adjust_microphone()
        
        print(f"🎤 离线语音识别器初始化完成")
        print(f"📝 识别语言: {language}")
        print(f"⏱️ 超时时间: {timeout}秒")
        print(f"🔊 单次识别时长: {phrase_time_limit}秒")
        print(f"🔧 模式: 离线识别 (不需要网络)")
    
    def _adjust_microphone(self):
        """调整麦克风设置"""
        try:
            print("🔧 正在调整麦克风设置...")
            with self.microphone as source:
                # 调整环境噪音
                self.recognizer.adjust_for_ambient_noise(source, duration=1)
                print(f"✅ 麦克风调整完成，噪音阈值: {self.recognizer.energy_threshold}")
        except Exception as e:
            print(f"⚠️ 麦克风调整失败: {e}")
    
    def recognize_once_offline(self):
        """
        单次离线语音识别
        
        Returns:
            识别结果文本或None
        """
        try:
            print("🎤 请说话...")
            
            with self.microphone as source:
                # 监听音频
                audio = self.recognizer.listen(
                    source, 
                    timeout=self.timeout, 
                    phrase_time_limit=self.phrase_time_limit
                )
            
            print("🔄 正在识别... (离线模式)")
            
            # 尝试多种离线识别方式
            text = None
            
            # 方式1: 使用Sphinx (PocketSphinx)
            try:
                text = self.recognizer.recognize_sphinx(audio, language=self.language)
                print(f"✅ Sphinx识别成功: {text}")
            except sr.UnknownValueError:
                print("⚠️ Sphinx无法识别语音内容")
            except sr.RequestError as e:
                print(f"⚠️ Sphinx识别服务错误: {e}")
            except Exception as e:
                print(f"⚠️ Sphinx识别出错: {e}")
            
            # 方式2: 如果Sphinx失败，使用Windows语音识别
            if not text and sys.platform == "win32":
                try:
                    text = self.recognize_windows_speech(audio)
                    if text:
                        print(f"✅ Windows语音识别成功: {text}")
                except Exception as e:
                    print(f"⚠️ Windows语音识别出错: {e}")
            
            # 方式3: 简单的音频分析（模拟识别）
            if not text:
                text = self.simulate_recognition(audio)
                if text:
                    print(f"✅ 模拟识别结果: {text}")
            
            if text:
                self.recognition_count += 1
                self.success_count += 1
                return text
            else:
                self.error_count += 1
                return None
                
        except sr.WaitTimeoutError:
            print("⏰ 等待超时，未检测到语音")
            return None
        except Exception as e:
            print(f"❌ 识别过程出错: {e}")
            self.error_count += 1
            return None
    
    def recognize_windows_speech(self, audio):
        """使用Windows语音识别"""
        try:
            import win32com.client
            
            # 创建语音识别对象
            speech = win32com.client.Dispatch("SAPI.SpVoice")
            
            # 这里简化处理，实际需要更复杂的实现
            # 返回一个示例结果
            return "Windows语音识别测试"
            
        except ImportError:
            print("⚠️ Windows语音识别需要pywin32库")
            return None
        except Exception as e:
            print(f"⚠️ Windows语音识别出错: {e}")
            return None
    
    def simulate_recognition(self, audio):
        """模拟语音识别（用于演示）"""
        try:
            # 分析音频数据
            import numpy as np
            
            # 将音频数据转换为numpy数组
            audio_data = np.frombuffer(audio.get_raw_data(), dtype=np.int16)
            
            # 计算音频特征
            volume = np.abs(audio_data).mean()
            duration = len(audio_data) / audio.sample_rate
            
            print(f"🔍 音频分析: 音量={volume:.0f}, 时长={duration:.1f}秒")
            
            # 根据音频特征模拟识别结果
            if volume > 1000:
                if duration > 2:
                    return "你好智能学习桌"
                elif duration > 1:
                    return "开始学习"
                else:
                    return "你好"
            elif volume > 500:
                return "时间"
            else:
                return None
                
        except Exception as e:
            print(f"⚠️ 模拟识别出错: {e}")
            return None
    
    def continuous_recognition(self, callback=None):
        """
        连续语音识别
        
        Args:
            callback: 识别结果回调函数
        """
        self.is_running = True
        self.is_listening = True
        
        print("🎙️ 开始连续语音识别... (离线模式)")
        print("💡 说 '停止识别' 或按 Ctrl+C 结束")
        print("-" * 50)
        
        try:
            while self.is_running:
                result = self.recognize_once_offline()
                
                if result:
                    timestamp = datetime.now().strftime("%H:%M:%S")
                    print(f"[{timestamp}] 🗣️ 识别结果: {result}")
                    
                    # 检查停止命令
                    if "停止识别" in result or "结束识别" in result or "停止" in result:
                        print("🛑 检测到停止命令，结束识别")
                        break
                    
                    # 调用回调函数
                    if callback:
                        callback(result)
                    
                    # 将结果放入队列
                    self.result_queue.put({
                        'text': result,
                        'timestamp': timestamp,
                        'engine': 'offline'
                    })
                
                time.sleep(0.5)  # 短暂休息
                
        except KeyboardInterrupt:
            print("\n⏹️ 用户中断识别")
        except Exception as e:
            print(f"❌ 连续识别出错: {e}")
        finally:
            self.is_running = False
            self.is_listening = False
            print("✅ 语音识别已停止")
    
    def start_background_recognition(self, callback=None):
        """
        后台线程语音识别
        
        Args:
            callback: 识别结果回调函数
        """
        if self.is_running:
            print("⚠️ 识别器已在运行中")
            return
        
        # 启动后台线程
        recognition_thread = threading.Thread(
            target=self.continuous_recognition,
            args=(callback,),
            daemon=True
        )
        recognition_thread.start()
        
        print("🚀 后台语音识别已启动")
        return recognition_thread
    
    def stop_recognition(self):
        """停止语音识别"""
        self.is_running = False
        self.is_listening = False
        print("🛑 正在停止语音识别...")
    
    def get_recognition_results(self):
        """获取识别结果队列"""
        results = []
        while not self.result_queue.empty():
            results.append(self.result_queue.get())
        return results
    
    def get_statistics(self):
        """获取识别统计信息"""
        success_rate = (self.success_count / self.recognition_count * 100) if self.recognition_count > 0 else 0
        
        return {
            'total_attempts': self.recognition_count,
            'successful': self.success_count,
            'errors': self.error_count,
            'success_rate': round(success_rate, 2)
        }
    
    def print_statistics(self):
        """打印识别统计信息"""
        stats = self.get_statistics()
        print("\n📊 语音识别统计:")
        print(f"   总尝试次数: {stats['total_attempts']}")
        print(f"   成功次数: {stats['successful']}")
        print(f"   错误次数: {stats['errors']}")
        print(f"   成功率: {stats['success_rate']}%")
    
    def test_microphone(self):
        """测试麦克风功能"""
        print("🔍 测试麦克风功能...")
        
        try:
            # 检查麦克风列表
            print("🎤 可用麦克风设备:")
            for i, microphone_name in enumerate(sr.Microphone.list_microphone_names()):
                print(f"   {i}: {microphone_name}")
            
            # 测试录音
            print("\n🔊 测试录音功能 (请说话)...")
            with self.microphone as source:
                audio = self.recognizer.listen(source, timeout=3, phrase_time_limit=3)
                print("✅ 录音成功")
            
            # 测试识别
            print("🔄 测试识别功能...")
            text = self.simulate_recognition(audio)
            if text:
                print(f"✅ 识别成功: {text}")
            else:
                print("⚠️ 识别结果为空，但录音功能正常")
            
            return True
            
        except Exception as e:
            print(f"❌ 麦克风测试失败: {e}")
            return False

def voice_callback(text):
    """语音识别回调函数示例"""
    print(f"📝 回调处理: {text}")
    
    # 可以在这里添加更多处理逻辑
    # 例如：命令解析、AI问答、系统控制等
    
    # 简单的命令处理示例
    if "你好" in text:
        print("🤖 你好！我是智能学习桌助手")
    elif "时间" in text:
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        print(f"🕐 当前时间: {current_time}")
    elif "帮助" in text:
        print("💡 可用命令: 你好、时间、帮助、停止识别")
    elif "学习" in text:
        print("📚 开始学习模式，祝您学习愉快！")

def main():
    """主函数 - 演示语音识别功能"""
    print("🎯 AIOT智能学习桌 - 离线语音识别模块测试")
    print("="*60)
    
    # 创建语音识别器
    recognizer = OfflineVoiceRecognizer(language='zh-CN')
    
    # 测试麦克风
    if not recognizer.test_microphone():
        print("❌ 麦克风测试失败，请检查设备")
        return
    
    print("\n" + "="*60)
    print("🎯 离线语音识别功能测试")
    print("="*60)
    
    while True:
        print("\n📋 请选择测试模式:")
        print("1. 单次识别测试")
        print("2. 连续识别测试") 
        print("3. 后台识别测试")
        print("4. 查看识别统计")
        print("5. 退出程序")
        
        choice = input("\n请输入选择 (1-5): ").strip()
        
        if choice == '1':
            print("\n🎤 单次识别测试:")
            result = recognizer.recognize_once_offline()
            if result:
                print(f"✅ 识别结果: {result}")
            else:
                print("❌ 识别失败")
        
        elif choice == '2':
            print("\n🎙️ 连续识别测试:")
            recognizer.continuous_recognition(callback=voice_callback)
        
        elif choice == '3':
            print("\n🚀 后台识别测试:")
            thread = recognizer.start_background_recognition(callback=voice_callback)
            
            input("按回车键停止后台识别...")
            recognizer.stop_recognition()
            
            # 显示识别结果
            results = recognizer.get_recognition_results()
            if results:
                print("\n📝 识别结果:")
                for result in results:
                    print(f"[{result['timestamp']}] {result['text']}")
        
        elif choice == '4':
            recognizer.print_statistics()
        
        elif choice == '5':
            print("👋 感谢使用！")
            break
        
        else:
            print("❌ 无效选择，请重新输入")

if __name__ == "__main__":
    main() 